﻿// -----------------------------------------------------------------------
// <copyright file="Radar.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace SpaceshipDuel
{
    using System;
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;

    /// <summary>
    /// Radar-Klasse
    /// </summary>
    public class Radar
    {
        #region Constants

        /// <summary>
        /// Skalierungsfaktor für Radar
        /// Radar Radius = 200 (Größe Radartextur)
        /// Abgebildete Weltgröße = 2000
        /// </summary>
        const int scale = 10;

        /// <summary>
        /// Radarradius
        /// Alle Objekte innerhalb des Radius 
        /// um das Schiff sind im Radar sichtbar
        /// </summary>
        const int radarRadius = 2000;

        #endregion Constants

        #region Public fields

        List<Vector2> objectList1;  // List of visible Objects for Player1 radar
        List<Vector2> objectList2;  // List of visible objects for Player2 radar

        #endregion Public fields

        #region Private fields

        Texture2D pixelTexture;
        int worldSize;
        Vector2 player1Pos, player2Pos;

        #endregion Private fields

        #region Construction

        /// <summary>
        /// Konstruktor
        /// </summary>
        public Radar(TextureData newPixelTexture, int newWorldSize)
        {
            pixelTexture = newPixelTexture.texture;
            worldSize = newWorldSize;
            objectList1 = new List<Vector2>();
            objectList2 = new List<Vector2>();
        }

        #endregion Construction

        #region Public methods

        /// <summary>
        /// Zurücksetzen der Objektlisten
        /// </summary>
        public void ResetObjectList()
        {
            objectList1.Clear();
            objectList2.Clear();
        }

        /// <summary>
        /// Update-Methode für Objektlisten
        /// </summary>
        public void UpdateObjectList(Vector2 objectPosition, Vector2 player1Position, Vector2 player2Position)
        {
            UpdateObjectListPlayer1(objectPosition, player1Position, -worldSize, -worldSize);
            UpdateObjectListPlayer1(objectPosition, player1Position, -worldSize,          0);
            UpdateObjectListPlayer1(objectPosition, player1Position, -worldSize,  worldSize);
            UpdateObjectListPlayer1(objectPosition, player1Position,          0, -worldSize);
            UpdateObjectListPlayer1(objectPosition, player1Position,          0,          0);
            UpdateObjectListPlayer1(objectPosition, player1Position,          0,  worldSize);
            UpdateObjectListPlayer1(objectPosition, player1Position,  worldSize, -worldSize);
            UpdateObjectListPlayer1(objectPosition, player1Position,  worldSize,          0);
            UpdateObjectListPlayer1(objectPosition, player1Position,  worldSize,  worldSize);
            
            UpdateObjectListPlayer2(objectPosition, player2Position, -worldSize, -worldSize);
            UpdateObjectListPlayer2(objectPosition, player2Position, -worldSize,          0);
            UpdateObjectListPlayer2(objectPosition, player2Position, -worldSize,  worldSize);
            UpdateObjectListPlayer2(objectPosition, player2Position,          0, -worldSize);
            UpdateObjectListPlayer2(objectPosition, player2Position,          0,          0);
            UpdateObjectListPlayer2(objectPosition, player2Position,          0,  worldSize);
            UpdateObjectListPlayer2(objectPosition, player2Position,  worldSize, -worldSize);
            UpdateObjectListPlayer2(objectPosition, player2Position,  worldSize,          0);
            UpdateObjectListPlayer2(objectPosition, player2Position,  worldSize,  worldSize);
        }

        /// <summary>
        /// Draw-Methode
        /// </summary>
        /// <param name="spriteBatch">Spritebatch</param>
        /// <param name="xOffset">Offset X</param>
        /// <param name="yOffset">Offset Y</param>
        public void Draw(SpriteBatch spriteBatch, Vector2 center, int player)
        {
            Vector2 translate = center / scale;// skalierte Größe des Zentrums (= Raumschiffposition) 
            float offsetX = center.X - translate.X;
            float offsetY = center.Y - translate.Y;

            if (player == 1)
            {
                for (int i = 0; i < objectList1.Count; i++)
                    spriteBatch.Draw(pixelTexture, new Rectangle((int)(objectList1[i].X + offsetX), (int)(objectList1[i].Y + offsetY), 2, 2), new Rectangle(0, 0, 1, 1), Color.White, 0f, new Vector2(0, 0), SpriteEffects.None, 0f);

                DrawPlayer(spriteBatch, center, player, offsetX, offsetY, -worldSize,  -worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,          0,  -worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,  worldSize,  -worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY, -worldSize,           0);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,          0,           0);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,  worldSize,           0);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY, -worldSize,   worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,          0,   worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,  worldSize,   worldSize);
            }
            else
            {
                for (int i = 0; i < objectList2.Count; i++)
                    spriteBatch.Draw(pixelTexture, new Rectangle((int)(objectList2[i].X + offsetX), (int)(objectList2[i].Y + offsetY), 2, 2), new Rectangle(0, 0, 1, 1), Color.White, 0f, new Vector2(0, 0), SpriteEffects.None, 0f);

                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,  -worldSize,  -worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,           0,  -worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,   worldSize,  -worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,  -worldSize,           0);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,           0,           0);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,   worldSize,           0);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,  -worldSize,   worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,           0,   worldSize);
                DrawPlayer(spriteBatch, center, player, offsetX, offsetY,   worldSize,   worldSize);
            }
        } 

        #endregion Public methods

        #region Private methods

        /// <summary>
        /// Objektliste für Radar Spieler 1 befüllen
        /// </summary>
        /// <param name="objectPosition"></param>
        /// <param name="player1Position"></param>
        /// <param name="xOffset"></param>
        /// <param name="yOffset"></param>
        private void UpdateObjectListPlayer1(Vector2 objectPosition, Vector2 player1Position, float xOffset, float yOffset)
        {
            float distance1 = new Vector2(Math.Abs(player1Position.X - objectPosition.X - xOffset), Math.Abs(player1Position.Y - objectPosition.Y - yOffset)).Length();

            if (distance1 < radarRadius)
                objectList1.Add(new Vector2((objectPosition.X + xOffset) / scale, (objectPosition.Y + yOffset) / scale));

            this.player1Pos = player1Position;
        }

        /// <summary>
        /// Objektliste für radar Spieler2 befüllen
        /// </summary>
        private void UpdateObjectListPlayer2(Vector2 objectPosition, Vector2 player2Position, float xOffset, float yOffset)
        {
            float distance2 = new Vector2(Math.Abs(player2Position.X - (objectPosition.X + xOffset)), Math.Abs(player2Position.Y - (objectPosition.Y + yOffset))).Length();

            if (distance2 < radarRadius)
                objectList2.Add(new Vector2((objectPosition.X + xOffset) / scale, (objectPosition.Y + yOffset) / scale));

            this.player2Pos = player2Position;
        }

        /// <summary>
        /// Zeichnet Spielerschiffe mit eigener Textur im Radar, damit diese von den anderen Objekten zu unterscheiden sind
        /// </summary>
        private void DrawPlayer(SpriteBatch spriteBatch, Vector2 center, int player, float radarOffsetX, float radarOffsetY, float worldOffsetX, float worldOffsetY)
        {
            float distance = new Vector2(Math.Abs(player1Pos.X - player2Pos.X + worldOffsetX), Math.Abs(player1Pos.Y - player2Pos.Y + worldOffsetY)).Length();
            if (distance < radarRadius)
            {
                if (player == 1)
                {
                    Vector2 p2Pos;
                    p2Pos = new Vector2((player2Pos.X + worldOffsetX) / scale, (player2Pos.Y + worldOffsetY) / scale);
                    spriteBatch.Draw(TextureProvider.TexRadarShip.texture, new Vector2((int)(p2Pos.X + radarOffsetX), (int)(p2Pos.Y + radarOffsetY)), Color.White);
                }
                else
                {
                    Vector2 p1Pos;
                    p1Pos = new Vector2((player1Pos.X + worldOffsetX) / scale, (player1Pos.Y + worldOffsetY) / scale);
                    spriteBatch.Draw(TextureProvider.TexRadarShip.texture, new Vector2((int)(p1Pos.X + radarOffsetX), (int)(p1Pos.Y + radarOffsetY)), Color.White);
                }
            }
        }

        #endregion private methods
    }
}
